# Copyright (c) 2011, Lawrence Livermore National Security, LLC.  
# Produced at the Lawrence Livermore National Laboratory  
# Written by Mason Kwiat and Douglas S. Miller,
# e-mail: dougmiller@llnl.gov
# LLNL-CODE-507071
# All rights reserved.  
  
# This file is part of PDV.  For details, see <URL describing code and
# how to download source>. Please also read "Additional BSD Notice".
  
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
  
# Redistributions of source code must retain the above copyright
# notice, this list of conditions and the disclaimer below.
# Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the disclaimer (as noted below)
# in the documentation and/or other materials provided with the
# distribution.  Neither the name of the LLNS/LLNL nor the names of
# its contributors may be used to endorse or promote products derived
# from this software without specific prior written permission.
 
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
# FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL LAWRENCE
# LIVERMORE NATIONAL SECURITY, LLC, THE U.S. DEPARTMENT OF ENERGY OR
# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
# USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
# OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
# SUCH DAMAGE.
    
# Additional BSD Notice  
  
# 1. This notice is required to be provided under our contract with
# the U.S.  Department of Energy (DOE).  This work was produced at
# Lawrence Livermore National Laboratory under Contract
# No. DE-AC52-07NA27344 with the DOE.
  
# 2. Neither the United States Government nor Lawrence Livermore
# National Security, LLC nor any of their employees, makes any
# warranty, express or implied, or assumes any liability or
# responsibility for the accuracy, completeness, or usefulness of any
# information, apparatus, product, or process disclosed, or represents
# that its use would not infringe privately-owned rights.
  
# 3.  Also, reference herein to any specific commercial products,
# process, or services by trade name, trademark, manufacturer or
# otherwise does not necessarily constitute or imply its endorsement,
# recommendation, or favoring by the United States Government or
# Lawrence Livermore National Security, LLC.  The views and opinions
# of authors expressed herein do not necessarily state or reflect
# those of the United States Government or Lawrence Livermore National
# Security, LLC, and shall not be used for advertising or product
# endorsement purposes.

import numpy as np

import pdvutil
import pdv

class Curve(object):

    name = ''
    filename = ''
    plotname = ''
    color = ''
    edited = False
    scatter = False
    linespoints = False
    linewidth = None
    linestyle = '-'
    dashes = None
    hidden = False
    x = np.empty(0)
    y = np.empty(0)
    ebar = None     #errorbar
    erange = None   #errorrange
    marker = '.'
    markersize = 6
    plotprecedence = 0
    
    def __init__(self, filename='', name=''):
        self.filename = filename
        self.name = name
    
    
    def __add__(a, b):
        c = Curve('', '')
        c.plotname = str(a.plotname + ' + ' + b.plotname + ' ').strip('  ')
        ia, ib = getinterp(a, b)
        if(ia.x != None and ib.x != None):
            c.x = ia.x
            c.y = ia.y + ib.y
        return c

    
    def __sub__(a, b):
        c = Curve('', '')
        c.plotname = str(a.plotname + ' - ' + b.plotname + ' ').strip('  ')
        ia, ib = getinterp(a, b)
        if(ia.x != None and ib.x != None):
            c.x = ia.x
            c.y = ia.y - ib.y
        return c
    
    
    def __mul__(a, b):
        c = Curve('', '')
        c.plotname = str(a.plotname + ' * ' + b.plotname + ' ').strip('  ')
        ia, ib = getinterp(a, b)
        if(ia.x != None and ib.x != None):
            c.x = ia.x
            c.y = ia.y * ib.y
        return c
        
        
    def __div__(a, b):
        c = Curve('', '')
        c.plotname = str(a.plotname + ' / ' + b.plotname + ' ').strip('  ')
        ia, ib = getinterp(a, b)
        if(ia.x != None and ib.x != None):
            c.x = ia.x
            c.y = ia.y / ib.y
        return c
    def __truediv__(a,b):
        return __div__(a,b) #future proofing for python 3.0
    
    
    def __pow__(a, b):
        c = Curve('', '')
        c.plotname = str(a.plotname + '^' + str(b)).strip('  ')
        c.x = np.array(a.x)
        c.y = np.power(a.y, b)
        nans = np.isnan(c.y)    #remove NaNs
        c.x = c.x[~nans]
        c.y = c.y[~nans]
        return c
        
    def __neg__(a):
        c = Curve('', '')
        c.plotname = str('-' + a.plotname)
        c.x = np.array(a.x)
        c.y = np.array(-a.y)
        return c
   
    
    ##return a new copy of the curve object##
    def copy(self):
        c = Curve(self.filename, self.name)
        c.plotname = self.plotname
        c.x = np.array(self.x)
        c.y = np.array(self.y)
        c.color = self.color
        c.edited = self.edited
        c.scatter = self.scatter
        c.linespoints = self.linespoints
        c.linewidth = self.linewidth
        c.linestyle = self.linestyle
        c.dashes = self.dashes
        c.hidden = self.hidden
        c.marker = self.marker
        c.markersize = self.markersize
        c.ebar = self.ebar
        c.erange = self.erange
        c.plotprecedence = self.plotprecedence
        
        return c

##return the interpolated and domain matched versions of the two curves##
def getinterp(a, b):
    ux = sorted(list(set(a.x) | set(b.x)))  #get union of xvals
    umax = min(max(a.x), max(b.x))
    umin = max(min(a.x), min(b.x))
    curx = []
    for item in ux:
        if(item <= umax and item >= umin):
            curx.append(item)
    ia = Curve('', '')
    ia.x, ia.y = pdvutil.interpol(curx, a.x, a.y)#np.interp(curx, a.x, a.y) #interpolate y vals
    ib = Curve('', '')
    ib.x, ib.y = pdvutil.interpol(curx, b.x, b.y)#np.interp(curx, b.x, b.y) #interpolate y vals
    return ia, ib
